#!/usr/bin/env python
#
# webserver.py
#
# Version : 0.6
# Date : 20080424
#
# Author : Bernard Czenkusz
# Email  : bernie@skipole.co.uk

#
# webserver.py - run as part of skipolemonitor
# Copyright (c) 2007 Bernard Czenkusz
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#

"""Defines the class WebServer and the function startup(port) which calls it.

startup(port) is run from the monitor module. It then starts a
web server in its own thread, listenning on 'port' and returns
1 on success, 0 on failure.

The class WebServer is derived from SimpleHTTPServer, and overrides
the translate_path and log_message methods.

The new method translate_path(self, path) defines path
using path=net.net_cfg["HTTPROOT"] rather than the current working
directory.

This has been done because it was found that the file picker, used for
importing an external file, temporarily changes the current working
directory, which messes up the web serving.

The log_message method is changed to a pass - to stop logging
"""

import SimpleHTTPServer
import SocketServer
import select
import net
import thread
import urlparse
import urllib
import os
import posixpath

# global flag to show web server running, used by the gui
WEB_RUNNING = False

def startup(port):    
    """Start the web server in a thread"""
    global WEB_RUNNING
    if net.net_cfg["WEB_SERVER_ENABLED"] == "0":
        WEB_RUNNING = False
        return 1
    try:
        Handler = SM_WebServer
        httpd = SM_TCPServer(("", int(port)), Handler)
    except:
        # The socket was not bound, so return a zero
        WEB_RUNNING = False
        return 0
    # The socket is bound ok, start serving it in a thread
    WEB_RUNNING = True
    thread.start_new_thread(httpd.serve_forever, ())
    # This does not "serve_forever" since the serve_forever method has
    # been overridden to check the net_cfg["WEB_SERVER_ENABLED"] and
    # PROGRAM_SHUTDOWN flags
    return 1    

    

class SM_TCPServer(SocketServer.TCPServer):
    """Overrides the serve_forever method, to allow closing down"""
    def serve_forever(self):
        """Handle one request at a time until the net_cfg["WEB_SERVER_ENABLED"]
           flag is not "1" """ 
        while net.net_cfg["WEB_SERVER_ENABLED"] == "1" and net.PROGRAM_SHUTDOWN == False:
            # Use select() to check if there is an incoming request
            try:
                r,w,e = select.select([self.socket], [], [], 1.0)
                if r:
                    self.handle_request()
            except:
                # If there's an error, just try again
                pass
        #
        # So to get here, the web service has stopped, flag this to the gui
        # to be shown on the bottom status bar
        global WEB_RUNNING
        WEB_RUNNING = False


class SM_WebServer(SimpleHTTPServer.SimpleHTTPRequestHandler):
    """Overrides translate_path to set the httproot port, and turns off logging"""
    
    def translate_path(self, path):
        """Translate a /-separated PATH to the local filename syntax.

        Components that mean special things to the local file system
        (e.g. drive or directory names) are ignored.  (XXX They should
        probably be diagnosed.)

        """
        # abandon query parameters
        path = urlparse.urlparse(path)[2]
        path = posixpath.normpath(urllib.unquote(path))
        words = path.split('/')
        words = filter(None, words)
        ### This is the original line that has been changed
        ### path = os.getcwd()
        ### instead it becomes the following line
        path=net.net_cfg["HTTPROOT"]
        ### and back to the original
        for word in words:
            drive, word = os.path.splitdrive(word)
            head, word = os.path.split(word)
            if word in (os.curdir, os.pardir): continue
            path = os.path.join(path, word)
        return path

    def log_message(self, format, *args):
        """Overrides, and turns off logging"""
        pass

